前面幾篇的發文已經大致的了解Vue的主要的特性及用法了,
接下來要轉到Vue的官網上的Example範例,
透過範例,來學習及驗證Vue的功能是否都有理解了,或是還有待確認的地方
經過幾篇的範例學習之後,就可以來挑戰一個小專案的規模了
首先,從 Markdown Editor 開始
來學習建立一個最簡單的 Markdown編輯器
網址如下
https://vuejs.org/examples/#markdown
這個範例只有一個App.vue
<!--
A simple markdown editor.
-->
<script setup>
import { marked } from 'marked'
import { debounce } from 'lodash-es'
import { ref, computed } from 'vue'
const input = ref('# hello')
const output = computed(() => marked(input.value))
const update = debounce((e) => {
input.value = e.target.value
}, 10000)
</script>
<template>
<div class="editor">
<textarea class="input" :value="input" @input="update"></textarea>
<div class="output" v-html="output"></div>
</div>
</template>
<style>
body {
margin: 0;
}
.editor {
height: 100vh;
display: flex;
}
.input,
.output {
overflow: auto;
width: 50%;
height: 100%;
box-sizing: border-box;
padding: 0 20px;
}
.input {
border: none;
border-right: 1px solid #ccc;
resize: none;
outline: none;
background-color: #f6f6f6;
font-size: 14px;
font-family: 'Monaco', courier, monospace;
padding: 20px;
}
code {
color: #f66;
}
</style>
Markdown 是一套可以在純文字編輯下透過特別符號符標記,
就可以轉換或是渲染成具有樣式的網頁內容
像是 # hello
就會渲染成 <h1>hello</h1>
[iT邦幫忙](https://ithelp.ithome.com.tw)
就會渲染成
<a href="https://ithelp.ithome.com.tw">iT邦幫忙</a>
**粗體** 就會渲染成 <strong>粗體</strong>
*斜體* 就會渲染成 <em>斜體</em>
詳細語法可以參考 Markdown說明 的網頁介紹
https://ithelp.ithome.com.tw/markdown
接著來看一下程式
先從<template>
看起
<template>
<div class="editor">
<textarea class="input" :value="input" @input="update"></textarea>
<div class="output" v-html="output"></div>
</div>
</template>
在<template>
中,有一個<textarea>
作為輸入原始純文字 Markdown 的區域,<div>
則是渲染成網頁內容的區塊。
在<textarea class="input">
中,宣告input變數綁定了value值 :value, 用function update綁定input事件@input,
在<div class="output">
中,用output設定v-html,
在<script setup>
的部份
<script setup>
import { marked } from 'marked'
import { debounce } from 'lodash-es'
import { ref, computed } from 'vue'
const input = ref('# hello')
const output = computed(() => marked(input.value))
const update = debounce((e) => {
input.value = e.target.value
}, 10000)
</script>
在<script setup>
中
import { marked } from 'marked'
import { debounce } from 'lodash-es'
這2個套件屬於要另外匯入,所以需要另外編輯 這些檔案 'tsconfig.json' 'Import Map'
也就是要有一個安裝的動作,以及套件路徑的設定,這樣程式才讀得到 'marked'
及 'lodash-es'
這部份屬於如何整合,加入外掛套件的部份,
會另外一篇發文來介紹
在此因為是利用官網上的線上編輯器,已經都是安裝好套件的狀態了。
input 是ref物件,初值是 '# hello'
會動態回應到 :value
output 是宣告接受 computed()
回傳的內容,這個內容是 將input.value
經過marked()
變成網頁格式內容marked()
是從 'marked'
套件匯入的 marked的功能
就是 import { marked } from 'marked'
另外 @input
事件,是在輸入文字內容時,觸發 function update,
update 會執行
debounce((e) => {
input.value = e.target.value
}, 1000)
其中看到debounce()
的功能,這是一個類似延後執行的意思,為了畢免太過頻繁的觸發update,
使用debounce( (e)=>{}, 1000)
就是輸入後間隔1000ms(毫秒),才對有觸發input的事件執行動作,
有點像是,在輸入的同時不會一直update, 而是輸入後1秒才會update,是一個針對輸入文字時,很有用的功能,
而這個 debounce()
的功能,也是要經過'lodash-es'
套件匯入
就是
import { debounce } from 'lodash-es'
再來就是 e.target.value 指的是 觸發的事件e, e.target是<textarea>
的事件對象,
e.target.value 是<textarea>
的value值,再傳給input.value
,input再連動到 <textarea :value="input">
這看起來像是自己輸入完1秒後更新<textarea>
的value內容
最後,再透過 const output = computed(() => marked(input.value))
,input.value
一變動,就立即更新到 <div class="output" v-html="output">
的內容
其中 v-html 參考vue.js官網的說明
https://vuejs.org/api/built-in-directives.html#v-html
是指對於綁定的內容,會照原始的內容格式呈現,就是 marked(input.value)
的結果是html的格式,加上v-html
綁定,就是<div>
的內容會以html的內容呈現,而不是當作純文字呈現,
因為會當作是html的內容呈現,如果輸入的是一些惡意的程式碼的話,就會被執行,造成資安的問題,
所以除非是在很信任的條件下,才能安全的使用v-html
。
在這個狀態下
<div class="output" v-html="output"></div>
像是如果輸入如下
# hello
<b>ABC</b>
<div onclick="alert('OK');"> AAA </div>
<a href="http://www.processing.org">processing</a>
<div class="output" v-html="output"></div>
<div class="output" v-html="output"></div>
# hello -> 會以h1標題呈現
<b>ABC</b> -> 會以粗體呈現
<div onclick="alert('OK');"> AAA </div> -> click時 會觸發執行alert('OK');
<a href="http://www.processing.org">processing</a> -> 會以超連結呈現,點下後可連到新網頁
若改成
<div class="output">{{ output }}</div>
的話
同樣的輸入
會變成有html格式純文字呈現了
<h1>hello</h1> <p><b>ABC</b></p> <div onclick="alert('OK');"> AAA </div> <p><a href="http://www.processing.org">processing</a></p>
在 <style>
的部份
.editor {
height: 100vh;
display: flex;
}
.input,
.output {
overflow: auto;
width: 50%;
height: 100%;
box-sizing: border-box;
padding: 0 20px;
}
會產生
<textarea class="input" :value="input" @input="update"></textarea>
<div class="output" v-html="output"></div>
左右並排的結果
若改成
.editor {
height: 100vh;
display: flex;
flex-direction: column;
}
.input,
.output {
overflow: auto;
width: 100%;
height: 50%;
box-sizing: border-box;
padding: 0 20px;
}
就會變成上下排列的結果
從這個範例可以嘗試找出要導入Vue的框架時,
思考的順序,綁定,連動,事件的連鎖關係,
像是先從基本的<template>
內容開始,
接著是各種的 綁定,連動,事件 的設定,
然後是在<script>
中,宣告對應的變數,ref物件,還有function的設定
最後是<style>
樣式的設定及綁定連動設定
後面的幾篇發文,可以藉此看看有什麼新的應用